<template>
  <div class="terminal-app">
    <div id="tab-bar-container">
      <div id="tab-bar" ref="tabBar"></div>
      <button id="new-terminal-button" ref="newTerminalButton">+</button>
    </div>
    <div id="terminal-container" ref="terminalContainer"></div>
  </div>
</template>

<script>
import { Terminal } from "xterm";
import { FitAddon } from "xterm-addon-fit";
import { invoke } from "@tauri-apps/api/core";
import { listen } from "@tauri-apps/api/event";

export default {
  name: "TerminalApp",
  data() {
    return {
      terminals: [],
      debouncedFitTerminal: null,
    };
  },
  mounted() {
    // 绑定新终端按钮的点击事件
    this.newTerminalButton?.addEventListener("click", this.createNewTerminal);

    // 监听来自 Tauri 的 exit_terminal 事件
    listen("exit_terminal", (event) => {
      const terminalId = event.payload;
      this.closeTerminal(terminalId);
    });

    // 初始化时创建第一个终端
    this.createNewTerminal();

    // 绑定窗口大小调整事件
    window.addEventListener("resize", this.debouncedFitTerminal);
  },
  beforeDestroy() {
    // 移除事件监听器
    this.newTerminalButton?.removeEventListener(
      "click",
      this.createNewTerminal
    );
    window.removeEventListener("resize", this.debouncedFitTerminal);

    // 关闭所有终端
    this.terminals.forEach((terminal) => {
      this.closeTerminal(terminal.id);
    });
  },
  computed: {
    newTerminalButton() {
      return this.$refs.newTerminalButton;
    },
    tabBar() {
      return this.$refs.tabBar;
    },
    terminalContainer() {
      return this.$refs.terminalContainer;
    },
  },
  methods: {
    // 创建新的终端实例
    async createNewTerminal() {
      try {
        const fitAddon = new FitAddon();
        const term = new Terminal({
          theme: {
            background: "#2f2f2f",
          },
        });
        term.loadAddon(fitAddon);

        const terminalElement = document.createElement("div");
        terminalElement.classList.add("terminal-instance");
        this.terminalContainer.appendChild(terminalElement);

        term.open(terminalElement);
        fitAddon.fit();
        term.focus();

        // 等待终端初始化
        await new Promise((resolve) => setTimeout(resolve, 10));

        const rows = term.rows;
        const cols = term.cols;

        // 调用 Tauri API 创建 shell
        const terminalId = await invoke("create_shell", { rows, cols });

        const writer = new PtyWriter(terminalId);

        let readInterval;

        // 开始读取终端输出
        const startReading = async () => {
          readInterval = window.setInterval(async () => {
             // 尝试从PTY读取数据
            try {
              const data = await invoke("read_pty", { terminalId });
              // 如果有数据，则将其写入终端
              if (data) {
                term.write(data);
              }
            } catch (error) {
              // 如果发生错误，则清除定时读取间隔
              clearInterval(readInterval);
            }
          }, 100);
        };

        startReading();

        // 监听终端输入
        term.onData((data) => {
          writer.enqueue(data);
        });

        // 创建标签
        const tabElement = document.createElement("button");
        // 为终端标签添加类名，以便于样式控制
        tabElement.classList.add("tab");
        // 设置终端标签的文本内容，显示当前是第几个终端
        tabElement.innerText = `终端 ${this.terminals.length + 1}`;

        const closeTabButton = document.createElement("button");
        closeTabButton.innerText = "×";
        closeTabButton.classList.add("close-tab");
        closeTabButton.addEventListener("click", (e) => {
          e.stopPropagation();
          this.closeTerminal(terminalId);
        });
        tabElement.appendChild(closeTabButton);

        // 点击标签激活对应的终端
        tabElement.addEventListener("click", () => {
          this.activateTerminal(terminalId);
        });

        this.tabBar.appendChild(tabElement);
        this.scrollTabBarToEnd();

        const terminalInstance = {
          id: terminalId,
          terminal: term,
          element: terminalElement,
          tabElement: tabElement,
          readInterval: readInterval,
          writer: writer,
        };
        this.terminals.push(terminalInstance);

        // 激活新创建的终端
        this.activateTerminal(terminalId);
      } catch (error) {
        console.error("创建新终端时出错:", error);
      }
    },

    // 激活指定的终端
    activateTerminal(terminalId) {
      this.terminals.forEach((t) => {
        if (t.id === terminalId) {
          t.element.classList.add("active");
          t.tabElement.classList.add("active");
          t.terminal.focus();
        } else {
          t.element.classList.remove("active");
          t.tabElement.classList.remove("active");
        }
      });
    },

    // 关闭指定的终端
    async closeTerminal(terminalId) {
      const terminalIndex = this.terminals.findIndex(
        (t) => t.id === terminalId
      );
      if (terminalIndex === -1) return;

      const terminalInstance = this.terminals[terminalIndex];

      try {
        await invoke("close_terminal", { terminalId });

        terminalInstance.element.remove();
        terminalInstance.tabElement.remove();
        clearInterval(terminalInstance.readInterval);

        this.terminals.splice(terminalIndex, 1);

        if (
          terminalInstance.tabElement.classList.contains("active") &&
          this.terminals.length > 0
        ) {
          this.activateTerminal(this.terminals[0].id);
        }
      } catch (error) {
        console.error(`关闭终端 ${terminalId} 时出错:`, error);
      }
    },

    // 滚动标签栏到末尾
    scrollTabBarToEnd() {
      this.tabBar.scrollTo({
        left: this.tabBar.scrollWidth,
        behavior: "smooth",
      });
    },

    // 防抖函数
    debounce(func, wait) {
      let timeout;
      return () => {
        clearTimeout(timeout);
        timeout = setTimeout(func, wait);
      };
    },

    // 调整终端大小
    async fitTerminal(term, fitAddon, terminalId) {
      try {
        fitAddon.fit();
        const updatedRows = term.rows;
        const updatedCols = term.cols;
        await invoke("resize_pty", {
          rows: updatedRows,
          cols: updatedCols,
        });
      } catch (error) {
        console.error(`调整终端 ${terminalId} 大小时出错:`, error);
      }
    },
  },
  created() {
    // 创建 debouncedFitTerminal 方法
    this.debouncedFitTerminal = this.debounce(() => {
      this.terminals.forEach((t) => {
        this.fitTerminal(t.terminal, new FitAddon(), t.id);
      });
    }, 200);
  },
};

// PtyWriter 类定义
class PtyWriter {
  constructor(terminalId) {
    this.queue = [];
    this.activeCount = 0;
    this.concurrency = 2;
    this.terminalId = terminalId;
  }

  enqueue(data) {
    this.queue.push(data);
    this.processQueue();
  }

  async processQueue() {
    if (this.activeCount >= this.concurrency || this.queue.length === 0) return;
    this.activeCount++;
    const data = this.queue.shift();
    try {
      await invoke("write_pty", { terminalId: this.terminalId, data });
    } catch (error) {
      console.error(`向终端 ${this.terminalId} 写入数据时出错:`, error);
    }
    this.activeCount--;
    this.processQueue();
  }
}
</script>

<style scoped>
.terminal-app {
  margin: 0;
  padding: 0;
  background-color: #2f2f2f;
  color: #fff;
  font-family: Arial, sans-serif;
  height: 100vh;
  display: flex;
  flex-direction: column;
}

#tab-bar-container {
  display: flex;
  align-items: center;
  background-color: #1e1e1e;
  padding: 5px;
  overflow: hidden;
  flex-shrink: 0;
}

#tab-bar {
  display: flex;
  flex-grow: 1;
  overflow-x: auto;
  white-space: nowrap;
}

.tab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 5px 10px;
  margin-right: 5px;
  background-color: #3c3c3c;
  color: #fff;
  border: none;
  cursor: pointer;
  border-radius: 3px;
  white-space: nowrap;
  min-width: 100px;
  flex-shrink: 0;
}

.tab.active {
  background-color: #555;
}

.tab .close-tab {
  margin-left: 10px;
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  font-size: 14px;
  padding: 0;
  line-height: 1;
}

#new-terminal-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin-left: 5px;
  background-color: #3c3c3c;
  color: #fff;
  border: none;
  border-radius: 3px;
  cursor: pointer;
  flex-shrink: 0;
  font-size: 20px;
  line-height: 20px;
  padding: 0;
}

#new-terminal-button:hover {
  background-color: #555;
}

#terminal-container {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.terminal-instance {
  display: none;
  position: relative;
  flex: 1;
  border: none;
  background-color: #2f2f2f;
}

.terminal-instance.active {
  display: block;
}

.terminal-instance button.close-terminal {
  position: absolute;
  top: 5px;
  right: 5px;
  z-index: 10;
  padding: 2px 5px;
  background-color: #ff4d4d;
  color: #fff;
  border: none;
  cursor: pointer;
}

#tab-bar::-webkit-scrollbar {
  height: 8px;
}

#tab-bar::-webkit-scrollbar-track {
  background: #1e1e1e;
}

#tab-bar::-webkit-scrollbar-thumb {
  background-color: #555;
  border-radius: 4px;
}
</style>
